package com.yang.smsgateway.config;

//静态导包，这样就不用重复写RabbitMQConstants
import static com.yang.common.constant.RabbitMQConstants.*;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitMQConfig {

    //声明死信队列，需要准备 1.普通交换机 2.普通队列 3.死信交换机 4.死信队列
    //原因:用延迟交换机也可以,但是交换机有个问题,没有办法确保消息一定不会丢。
    //而死信队列是把消息先放到普通队列上后，才会时间到了之后才会放到死信交换机，在放到死信队列中。可以确保消息不丢失、
    //而推送模块用的是延迟交换机。不保证100%推送成功。

    //普通交换机
    @Bean
    public Exchange normalExchange(){
        return ExchangeBuilder.fanoutExchange(SMS_GATEWAY_NORMAL_EXCHANGE).build();
    }

    //普通队列
    @Bean
    public Queue normalQueue(){
        //设置普通队列属性，生存时间和绑定的死信交换机。通过withArguments。也可以通过withArgument一个一个设置
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-message-ttl",10 * 1000);//10秒
        arguments.put("x-dead-letter-exchange",SMS_GATEWAY_DEAD_EXCHANGE);//绑定死信交换机
        arguments.put("x-dead-letter-routing-key","");//routing-key，fanoutExchange设置routing-key无意义，这里给的是空

        Queue queue = QueueBuilder.durable(SMS_GATEWAY_NORMAL_QUEUE)
                .withArguments(arguments)
                .build();
        return queue;
    }

    //将普通交换机和普通队列进行绑定，注意名称（详细见笔记下面补充的）
    @Bean
    public Binding normalBinding(Exchange normalExchange,Queue normalQueue){
        return BindingBuilder.bind(normalQueue).to(normalExchange).with("").noargs();
    }

    //死信交换机，本质是一个普通交换机
    @Bean
    public Exchange deadExchange(){
        return ExchangeBuilder.fanoutExchange(SMS_GATEWAY_DEAD_EXCHANGE).build();
    }

    //死信队列，本质还是一个普通队列
    @Bean
    public Queue deadQueue(){
        return QueueBuilder.durable(SMS_GATEWAY_DEAD_QUEUE).build();
    }

    //绑定
    @Bean
    public Binding deadBinding(Exchange deadExchange,Queue deadQueue){
        return BindingBuilder.bind(deadQueue).to(deadExchange).with("").noargs();
    }

    //MQ多线程消费
    @Bean
    public SimpleRabbitListenerContainerFactory gatewayContainerFactory(ConnectionFactory connectionFactory,SimpleRabbitListenerContainerFactoryConfigurer configurer){
        SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory = new SimpleRabbitListenerContainerFactory();
        //等价在配置文件中的spring.rabbitmq.listener.simple.concurrency = 5
        //注意：正常这种 5 10 常量都是写在配置文件中,这里就省略掉了
        simpleRabbitListenerContainerFactory.setConcurrentConsumers(5);
        //等价在配置文件中spring.rabbitmq.listener.simple.prefetch = 10
        simpleRabbitListenerContainerFactory.setPrefetchCount(10);
        //等价在配置文件中spring.rabbitmq.listener.simple.acknowledge-mode = manual
        simpleRabbitListenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        configurer.configure(simpleRabbitListenerContainerFactory,connectionFactory);
        return simpleRabbitListenerContainerFactory;
    }
}
